﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Xenta.Security;
using Xenta.Utils;

namespace Xenta.Operations
{
    public class ExportLanguagePack : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("GLBLZ");
            }
        }

        #endregion

        #region Utilities

        protected override Err Validate(IUnitOfWork uow)
        {
            if(Properties == null)
                return Err.Of(this).NotValid("Properties");
            if(!Properties.ContainsKey("id"))
                return Err.Of(this).NotSpecified("id");
            return base.Validate(uow);
        }

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            var ret = new List<IDictionary<String, String>>();
            var content = uow.Execute(new GetLanguagePackContent
            {
                EntityID = Properties["id"].ParseAs<Int32>()
            }).Result;
            if(content != null)
            {
                foreach(var i in content)
                {
                    ret.Add(new Dictionary<String, String>
                    {
                        {"key", i.Key},
                        {"value", i.Value}
                    });
                }
            }
            result = ret;
        }

        #endregion
    }

    public class ExportLanguagePacks : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("GLBLZ");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            var ret = new List<IDictionary<String, String>>();
            var languages = uow.Execute(new SearchLanguages()).Result;
            var packs = uow.Execute(new SearchLanguagePacks()).Result
                .AsEnumerable();

            if(Properties != null && Properties.ContainsKey("filter"))
            {
                var filter = Properties["filter"].Split(new []
                {
                    ','
                }, StringSplitOptions.RemoveEmptyEntries);
                if(filter.Any())
                    packs = packs.Where(x => filter.Contains(x.Code));
            }
            foreach(var g in packs.GroupBy(x => x.Code))
            {
                var tmp = new Dictionary<String, IDictionary<String, String>>();
                foreach(var l in languages)
                {
                    var content = g.Any(x => x.Language.Equals(l))
                        ? uow.Execute(new GetLanguagePackContentByCode
                        {
                            Code = g.Key,
                            LanguageID = l.EntityID
                        }).Result
                        : null;
                    tmp.Add(l.Code, content);
                }
                var keys = tmp.Values.Where(x => x != null)
                    .SelectMany(x => x.Keys)
                    .Distinct();
                foreach(string k in keys)
                {
                    var obj = new Dictionary<String, String>
                    {
                        {"code", g.Key},
                        {"key", k},
                    };
                    foreach(var l in languages)
                    {
                        string value = tmp[l.Code] != null && tmp[l.Code].ContainsKey(k)
                            ? tmp[l.Code][k]
                            : String.Empty;
                        obj.Add(l.Code, value);
                    }
                    ret.Add(obj);
                }
            }
            result = ret;
        }

        #endregion
    }

    public class ExportLanguages : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("GLBLZ");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new SearchLanguages()).Result
                .Select(x => new Dictionary<String, String>
                {
                    {"EntityID", x.EntityID.ToString()},
                    {"Code", x.Code},
                    {"Name", x.Name},
                    {"Flags", x.Flags.ToString()}
                }).ToList();
        }

        #endregion
    }

    public class ExportTimeZones : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("GLBLZ");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new SearchTimeZones()).Result
                .Select(x => new Dictionary<String, String>
                {
                    {"EntityID", x.EntityID.ToString()},
                    {"Code", x.Code},
                    {"Name", x.Name},
                    {"UtcOffset", x.UtcOffset.ToString()},
                    {"Flags", x.Flags.ToString()}
                }).ToList();
        }

        #endregion
    }

    public class ExportCurrencies : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("GLBLZ");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new SearchCurrencies()).Result
                .Select(x => new Dictionary<String, String>
                {
                    {"EntityID", x.EntityID.ToString()},
                    {"Code", x.Code},
                    {"Name", x.Name},
                    {"PriceFormat", x.PriceFormat},
                    {"Rate", x.Rate.ToString(CultureInfo.InvariantCulture)},
                    {"Flags", x.Flags.ToString()}
                }).ToList();
        }

        #endregion
    }

    public class ExportMeasureUnits : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("GLBLZ");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new SearchMeasureUnits()).Result
                .Select(x => new Dictionary<String, String>
                {
                    {"EntityID", x.EntityID.ToString()},
                    {"Code", x.Code},
                    {"Name", x.Name},
                    {"ValueFormat", x.ValueFormat},
                    {"Ratio", x.Ratio.ToString(CultureInfo.InvariantCulture)},
                    {"Flags", x.Flags.ToString()}
                }).ToList();
        }

        #endregion
    }

    public class ExportCountries : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("GLBLZ");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new SearchCountries()).Result
                .Select(x => new Dictionary<String, String>
                {
                    {"EntityID", x.EntityID.ToString()},
                    {"Code", x.Code},
                    {"Name", x.Name},
                    {"TimeFormat", x.TimeFormat},
                    {"DateFormat", x.DateFormat},
                    {"NumericFormat", x.NumericFormat.ToString()},
                    {"Flags", x.Flags.ToString()}
                }).ToList();
        }

        #endregion
    }

    public class ExportRegions : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("GLBLZ");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new SearchRegions()).Result
                .Select(x => new Dictionary<String, String>
                {
                    {"EntityID", x.EntityID.ToString()},
                    {"Country", x.Country.Code},
                    {"Code", x.Code},
                    {"Name", x.Name},
                    {"Flags", x.Flags.ToString()}
                }).ToList();
        }

        #endregion
    }

    public class ExportConfigParams : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("SYS");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new GetConfigParamDictionary()).Result
                .Select(x => new Dictionary<String, String>
                {
                    {"key", x.Key},
                    {"value", x.Value}
                }).ToList();
        }

        #endregion
    }

    public class ExportRoles : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("ACL");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new SearchRoles()).Result
                .Select(x => new Dictionary<String, String>
                {
                    {"EntityID", x.EntityID.ToString()},
                    {"Code", x.Code},
                    {"Name", x.Name},
                    {"Flags", x.Flags.ToString()},
                    {"Permissions", x.Permissions.Select(i => i.EntityID.ToString()).Merge(",")}
                }).ToList();
        }

        #endregion
    }

    public class ExportPermissions : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("ACL");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            result = uow.Execute(new SearchPermissions()).Result
                .Select(i => new Dictionary<String, String>
                {
                    {"EntityID", i.EntityID.ToString()},
                    {"Code", i.Code},
                    {"Name", i.Name},
                    {"Flags", i.Flags.ToString()}
                }).ToList();
        }

        #endregion
    }

    public class ExportMessageTemplates : ExportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("MSG");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out IEnumerable<IDictionary<String, String>> result)
        {
            var ret = new List<IDictionary<String, String>>();
            var languages = uow.Execute(new SearchLanguages()).Result;

            foreach(var i in uow.Execute(new SearchMessageTemplates()).Result)
            {
                var obj = new Dictionary<String, String>
                {
                    {"EntityID", i.EntityID.ToString()},
                    {"Code", i.Code},
                    {"SenderID", i.SenderID.ToString()},
                    {"From", i.From},
                    {"To", i.To},
                    {"BccTo", i.BccTo},
                    {"ReplyTo", i.ReplyTo},
                    {"Flags", i.Flags.ToString()}
                };
                foreach(var l in languages)
                {
                    string subjectKey = String.Format("subject({0})", l.Code);
                    string textKey = String.Format("text({0})", l.Code);
                    var t = i.Translation(l.EntityID);

                    obj.Add(subjectKey, t != null ? t.Subject : i.Code);
                    obj.Add(textKey, t != null ? t.Text : i.Code);
                }
                ret.Add(obj);
            }
            result = ret;
        }

        #endregion
    }
}
